﻿using Microsoft.Extensions.Logging;
using Sgr.Data;
using Sgr.Domain.Uow;
using Sgr.UPMS.Domain.Menus;
using Sgr.Utilities;
using System.Text.Json;

namespace Sgr.UPMS.Infrastructure.Sead
{
    /// <summary>
    /// 系统菜单数据初始化器
    /// </summary>
    public class MenuDataBaseInitialize : IDataBaseInitialize
    {
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IMenuManage _menuManage;
        private readonly IMenuRepository _menuRepository;
        private readonly ILogger<MenuDataBaseInitialize> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="unitOfWorkManager">工作单元管理器</param>
        /// <param name="menuManage">菜单管理服务</param>
        /// <param name="menuRepository">菜单仓储</param>
        /// <param name="logger">日志记录器</param>
        public MenuDataBaseInitialize(
            IUnitOfWorkManager unitOfWorkManager,
            IMenuManage menuManage,
            IMenuRepository menuRepository,
            ILogger<MenuDataBaseInitialize> logger)
        {
            _unitOfWorkManager = unitOfWorkManager;
            _menuManage = menuManage;
            _menuRepository = menuRepository;
            _logger = logger;
        }

        /// <summary>
        /// 获取初始化执行顺序，值越大越靠后执行
        /// </summary>
        public int Order => 999;

        /// <summary>
        /// 执行菜单数据初始化
        /// </summary>
        public async Task Initialize()
        {
            try
            {
                // 检查菜单表是否已存在数据
                var count = await _menuRepository.CountAsync();
                if (count > 0)
                {
                    return;
                }

                // 构建菜单配置文件路径
                var jsonPath = Path.Combine(LocalFileHelper.GetApplicationDirectory(), "Sead", "sysytem_menus.json");
                if (!File.Exists(jsonPath))
                {
                    _logger.LogWarning("未找到菜单配置文件: {Path}", jsonPath);
                    return;
                }

                // 加载菜单配置
                MenuConfigRoot? menuConfig = await LoadMenuConfigRootFromJson(jsonPath);
                if (menuConfig?.Menus == null || menuConfig.Menus.Count == 0)
                {
                    return;
                }

                // 递归创建菜单
                _logger.LogInformation("开始初始化系统菜单...");
                foreach (var menuItem in menuConfig.Menus)
                {
                    await CreateMenuRecursively(menuItem, null);
                }
                _logger.LogInformation("系统菜单初始化完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "菜单初始化过程中发生异常");
            }
        }

        /// <summary>
        /// 从JSON文件加载菜单配置
        /// </summary>
        /// <param name="jsonPath">JSON文件路径</param>
        /// <returns>菜单配置根节点</returns>
        private async Task<MenuConfigRoot?> LoadMenuConfigRootFromJson(string jsonPath)
        {
            MenuConfigRoot? menuConfig = null;
            try
            {
                var jsonContent = await File.ReadAllTextAsync(jsonPath);
                menuConfig = JsonHelper.DeserializeObject<MenuConfigRoot>(jsonContent);
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "菜单配置文件解析失败: {Path}", jsonPath);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "读取菜单配置文件时发生异常: {Path}", jsonPath);
            }

            return menuConfig;
        }

        /// <summary>
        /// 递归创建菜单及其子菜单
        /// </summary>
        /// <param name="menuConfig">菜单配置</param>
        /// <param name="parentId">父级菜单ID</param>
        /// <param name="depth"></param>
        /// <param name="maxDepth"></param>
        private async Task CreateMenuRecursively(MenuConfig menuConfig, long? parentId, int depth = 0, int maxDepth = 5)
        {
            if (depth > maxDepth)
            {
                _logger.LogWarning(
                    "菜单层级超过最大深度 {MaxDepth}，菜单: {MenuName}, 父菜单ID: {ParentId}",
                    maxDepth, menuConfig.Name, parentId
                );
                return;
            }

            // 创建当前菜单
            var menu = await Create(
                name: menuConfig.Name,
                type: menuConfig.Type,
                parentId: parentId,
                permission: menuConfig.Permission,
                icon: menuConfig.Icon,
                routeName: menuConfig.RouteName,
                routePath: menuConfig.RoutePath,
                componentPath: menuConfig.ComponentPath,
                redirectPath: menuConfig.RedirectPath,
                order: menuConfig.Order,
                externalLink: menuConfig.ExternalLink,
                hidden: menuConfig.Hidden,
                keepAlive: menuConfig.KeepAlive,
                affix: menuConfig.Affix,
                target: TargetType.Self
            );

            // 递归创建子菜单
            if (menu != null && menuConfig.Children != null && menuConfig.Children.Count > 0)
            {
                foreach (var child in menuConfig.Children)
                {
                    await CreateMenuRecursively(child, menu!.Id, depth + 1, maxDepth);
                }
            }
        }

        /// <summary>
        /// 创建菜单实体
        /// </summary>
        /// <param name="name">菜单名称</param>
        /// <param name="type">菜单类型</param>
        /// <param name="parentId">父级菜单ID</param>
        /// <param name="permission">权限标识</param>
        /// <param name="icon">菜单图标 (可选)</param>
        /// <param name="routeName">路由名称</param>
        /// <param name="routePath">路由路径</param>
        /// <param name="componentPath">组件路径</param>
        /// <param name="redirectPath">重定向</param>
        /// <param name="description">描述信息</param>
        /// <param name="order">排序号</param>
        /// <param name="externalLink">是否为外部链接</param>
        /// <param name="hidden">是否在菜单中隐藏</param>
        /// <param name="keepAlive">是否启用页面缓存</param>
        /// <param name="affix">是否固定在标签栏</param>
        /// <param name="target">打开方式</param>
        /// <returns></returns>
        private async Task<Menu?> Create(string name,
            MenuType type,
            long? parentId = null,
            string? permission = null,
            string? icon = null,
            string? routeName = null,
            string? routePath = null,
            string? componentPath = null,
            string? redirectPath = null,
            string? description = null,
            int order = 100,
            bool externalLink = false,
            bool hidden = false,
            bool keepAlive = false,
            bool affix = false,
            TargetType? target = null)
        {
            Menu? result;

            // 启动新的工作单元（事务）
            using var uow = _unitOfWorkManager.Begin(requiresNew: true);
            try
            {
                // 规则1：同级菜单名称唯一性
                // 规则2：菜单层级不超过5级
                // 规则3：目录节点只能放置到目录节点下
                // 规则4：菜单节点只能放置到目录节点下
                var menu = await _menuManage.CreateAsync(name, type, parentId, permission);

                // 设置基本信息
                menu.UpdateBasicInfo(name, icon, routeName, routePath, componentPath, redirectPath, permission, description, order);

                // 设置配置信息
                menu.UpdateConfig(externalLink, hidden, keepAlive, affix, target);

                // 保存菜单
                result = await _menuRepository.InsertAsync(menu);

                await uow.CommitAsync();

                _logger.LogInformation("菜单创建成功: {MenuName} (ID: {MenuId})", name, menu.Id);
                return menu;
            }
            catch (Exception ex)
            {
                result = null;
                _logger.LogError(ex, "菜单创建失败: {MenuName}", name);
                await uow.RollbackAsync();
            }

            return result;
        }

        /// <summary>
        /// 菜单配置模型
        /// </summary>
        private class MenuConfig
        {
            /// <summary>
            /// 菜单名称
            /// </summary>
            public string Name { get; set; } = string.Empty;

            /// <summary>
            /// 菜单类型
            /// </summary>
            public MenuType Type { get; set; }

            /// <summary>
            /// 菜单图标
            /// </summary>
            public string? Icon { get; set; }

            /// <summary>
            /// 路由名称
            /// </summary>
            public string? RouteName { get; set; }

            /// <summary>
            /// 路由路径
            /// </summary>
            public string? RoutePath { get; set; }

            /// <summary>
            /// 组件路径
            /// </summary>
            public string? ComponentPath { get; set; }

            /// <summary>
            /// 重定向路径
            /// </summary>
            public string? RedirectPath { get; set; }

            /// <summary>
            /// 权限标识
            /// </summary>
            public string? Permission { get; set; }

            /// <summary>
            /// 排序号
            /// </summary>
            public int Order { get; set; }

            /// <summary>
            /// 是否为外部链接
            /// </summary>
            public bool ExternalLink { get; set; }

            /// <summary>
            /// 是否在菜单中隐藏
            /// </summary>
            public bool Hidden { get; set; }

            /// <summary>
            /// 是否启用页面缓存
            /// </summary>
            public bool KeepAlive { get; set; }

            /// <summary>
            /// 是否固定在标签栏
            /// </summary>
            public bool Affix { get; set; }

            /// <summary>
            /// 子菜单列表
            /// </summary>
            public List<MenuConfig>? Children { get; set; }
        }

        /// <summary>
        /// 菜单配置根节点
        /// </summary>
        private class MenuConfigRoot
        {
            /// <summary>
            /// 菜单列表
            /// </summary>
            public List<MenuConfig> Menus { get; set; } = new();
        }
    }
}